package examples.mail;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayHandler;
import org.apache.commons.dbutils.handlers.ColumnListHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.lang.StringUtils;

public class MainTestUser2 {

	BlockingQueue<String> bq = new LinkedBlockingQueue<String>();
	Random rand = new Random();

	Map<String, List<String>> m = new ConcurrentHashMap<String, List<String>>();

	QueryRunner qr = null;
	private Connection conn = null;
	private PreparedStatement ps = null;
	public int i = 0;

	public MainTestUser2() throws Exception {
		qr = new QueryRunner();
		conn = Db.getDataSource().getConnection();
		conn.setAutoCommit(false);
		ps = conn.prepareStatement("update acc_csdn set stat=?  where too=? ");
	}

	synchronized public void update(String too, String stat) {
		try {
			qr.fillStatement(ps, stat, too);
			ps.addBatch();
			i++;
			System.out.println(i + "|" + too + "|" + stat);
			if (i > 50) {
				ps.executeBatch();
				conn.commit();
				i = 0;
			}
		} catch (SQLException e) {
			e.printStackTrace();

			System.exit(-1);
		}

	}

	class SendThread extends Thread {

		public void run() {

			while (true) {
				try {
					Thread.sleep(500);
				} catch (InterruptedException e2) {
					e2.printStackTrace();
				}

				ExecutorService executor = Executors.newSingleThreadExecutor();

				FutureTask<String> futureTask = null;
				String to1 = null;
				try {

					String to = bq.poll();
					//System.out.println("--------------->" + bq.size());

					if (to == null) {
						fetch();
						to = bq.poll();
					}

					to1 = to;

					Pattern regex = Pattern
							.compile("^[a-z0-9\\._-]{1,}@([a-z0-9-]{1,}\\.){1,3}[a-z]{2,4}$");
					Matcher matcher = regex.matcher(to);
					if (!matcher.matches()) {
						// qr.update("update acc_csdn set stat='mail.add.error'  where too=? ",
						// to);
						update(to, "mail.add.error");
						continue;
					}

					String hostName = to.split("@")[1];

					// System.out.println(to);
					/*
					 * if (hostName.equals("qq.com")) { update(to,"qq");
					 * continue; } if (hostName.equals("hotmail.com")) {
					 * update(to,"hotmail"); continue; } if
					 * (hostName.equals("msn.com")) { update(to,"msn");
					 * continue; }
					 */

					List<String> mxs = null;

					if (m.containsKey(hostName)) {
						mxs = m.get(hostName);

					} else {
						mxs = DnsResolver.getMXRecordsForHost(hostName);
						if (mxs == null) {
							// qr.update("update acc_csdn set stat='nomx'  where too=? ",
							// to);
							update(to, "nomx");
							continue;
						}
						m.put(hostName, mxs);
					}

					int r = Math.abs(rand.nextInt());
					final String toserver = mxs.get(r % mxs.size());

					String mailserver_1 = Util.randomString(10) + ".qq.com";
					String from_1 = Util.randomString(10) + "@qq.com";

					if (hostName.contains("sina.com")
							|| hostName.contains("sina.cn")) {
						 
						mailserver_1="mail.12306.cn";
						from_1="12306@rails.com.cn";
						 
					}

					final String mailserver = mailserver_1;

					final String from = from_1;

					final String to2 = to;

					futureTask = new FutureTask<String>(new Callable<String>() {
						public String call() throws Exception {

							SMTPUtil.testUser(from, to2, toserver, mailserver);

							return "";
						}
					});

					executor.execute(futureTask);

					String result = futureTask
							.get(20000, TimeUnit.MILLISECONDS); //

					futureTask.cancel(true);

					// qr.update("update acc_csdn set stat='1'  where too=? ",
					// to);

					update(to, "1");

				} catch (TimeoutException e) {

					try {
						// qr.update("update acc_csdn set stat=?  where too=? ",
						// msg, to1);
						update(to1, "timeout");
					} catch (Exception e1) {
						// e.printStackTrace();
					}

				} catch (Throwable e) {
					// e.printStackTrace();

					if (futureTask != null) {
						futureTask.cancel(true);
					}

					try {
						String msg = e.getMessage();
						if (msg == null) {
							msg = e.getClass().getName();
						}

						if (msg != null && msg.length() > 150) {

							msg = msg.substring(0, 150);
						}
						msg = msg.toLowerCase();
						// System.out.println(msg);
						// qr.update("update acc_csdn set stat=?  where too=? ",
						// msg, to1);
						update(to1, msg);
					} catch (Exception e1) {
						e1.printStackTrace();
					}
				} finally {
					executor.shutdownNow();
					executor = null;
				}

				/*
				 * try { Thread.sleep(500); } catch (InterruptedException e) {
				 * e.printStackTrace(); }
				 */

			}
		}
	}

	public synchronized void fetch() {

		if (this.bq.size() > 0) {
			System.out.println("done fetching ");
			return;
		} else {
			System.out.println("fetching ");

			String sql =
			"select too from acc_csdn where stat='0' and att<>'sina.com' and  att<>'163.com'  and att<>'126.com' and att<>'yeah.net'  and att<>'21cn.com'   limit 1000000     ";
			//String sql = "select too from acc_csdn where stat='0' "
				//	+ " order by test limit  10000 ";

			List<Object> tos;
			try {
				tos = qr.query(conn, sql, new ColumnListHandler("too"));
				if (tos == null || tos.size() == 0) {
					System.exit(-1);
				}

				for (Object to1 : tos) {
					String to = (String) to1;
					bq.add(to);
				}

			} catch (SQLException e) {
				e.printStackTrace();
				System.exit(0);
			}
			/* try {
					Util.changeip();
				} catch (Exception e) {
					e.printStackTrace();
				} */

		}

	

	}

	public void start() throws Exception {

		// bq.clear();
		// bq.add("yangelhun@126.com");

		for (int i = 0; i < 10; i++) {
			new SendThread().start();
		}

	}

	public static void main(String[] args) throws Exception {
		new MainTestUser2().start();
	}
}
